<?php
class SsoWS_Service_User
{
	/**
	 * Envia un mail con el link donde tiene que ingresar para resetear su clave
	 * Mas adalente tendria que pedirse la credencial de la aplicacion para poder ejecutar
	 * esta operacion 
	 * @param integer $username
	 * @return boolean true|false
	 */
	public function resetPassword( $username, $callback )
	{
		try{
			
			return true;	
		} catch( Exception $e )	{
			throw new Ext_Exception($e);
		}
	
	}
	
	/**
	 * (cacheable) Devuelve la credencial del usuario.
	 * 
	 * @param string $username
	 * @return string Credential
	 */
	public function getCredential( $token )
	{
		if( empty( $token )){
			throw new Ext_Exception("El token es requerido");
		}
		try{
			$loginStatus = new SsoWS_Model_UserLoginStatus ();
			$userId = $loginStatus->getRowByToken($token)->user_id;
			if( empty($userId )){
				throw new Ext_Exception("El usuario no esta logueado en el sso");
			}
			$user = new Ext_Model_User();
			return $user->getCredential( $userId	);
		}catch( Exception $e ) {
			throw new Ext_Exception( $e );
		}
	}

	/**
	 * (cacheable) Devuelve la credencial del usuario.
	 * 
	 * @param string $userId
	 * @return string Credential
	 */
	public function getCredentialFromId( $userId, $token)
	{
		if( empty( $userId )){
			throw new Ext_Exception("El userId es requerido");
		}
		try{
			$user = new Ext_Model_User();
			return $user->getCredential( $userId);
		}catch( Exception $e ) {
			throw new Ext_Exception( $e );
		}
	}
	
	/**
	 * 
	 * (cacheable) Chequea que la credencial
	 * @param string $userId
	 * @param string $credential
	 * @return boolean true|false
	 */
	public function checkCredential( $userId, $credential)
	{
		if( empty( $userId) || empty( $credential)) {
			throw new Ext_Exception("El token y la credencial son requerido");
		}
		try{
			$user = new Ext_Model_User();
			return $user->checkCredential( $userId, $credential );
		}catch( Exception $e ) {
			if( $e->getCode() == 101 ) {
				return false;
			}
			throw new Ext_Exception( $e );
		}	
	}
	
	/**
	 * 
	 * Validacion y logueo de usuarios
	 * @param string Username
	 * @param string Password
	 * @param string ApplicationId
	 * @return mixed false|true|array 
	 */
	public function login( $username = null, $password = null, $applicationId = 1)
	{
		$user = new Ext_Model_User();
		if( count( $user->getAuthenticatedUser( 
			$username, 
			$password, 
			Zend_Registry::get('config')->user->login->ownerId )) ){
			try{
				$userId = $user->getUserId( $username ); 
				$loginStatus = new SsoWS_Model_UserLoginStatus ();
				$row = $loginStatus->getRow( $userId );
				$row->user_id = $userId;
				$row->token = $loginStatus->getToken( $userId );
			    $row->is_login = 'T';
				//$row->last_login = Ext_Db_Date::now()->getDateDbExpr();
				//$row->expiration_date = $row->last_login->addDay('2');
				$row->save();
				return array(
					'token' => $row->token,
					'url'  => Zend_Registry::get('config')->api->externallogin->url . $row->token
				);
			} catch( Exception $e ) {
				throw new Ext_Exception( $e );	
			}
		} else {
			return false;
		}
			
	}
	
	/**
	 *	
	 *	(cacheable) Averigua el estado de un usuario, si esta online devuelve los datos apra que 
	 *	Se pueda loguear en la aplicacion que pregunta
	 *  @param string Username
	 *  @return mixed False|Token
	 */
	public function getStatus( $username = null )
	{
		try{
			$loginStatus = new SsoWS_Model_UserLoginStatus ();
		
			if( isset( $_COOKIE[ Zend_Registry::get('config')->cookie->token->name ] ) ){
				$token = $_COOKIE[ Zend_Registry::get('config')->cookie->token->name ];
				if( $loginStatus->getStatus( $token ) == 'T' ) {
					return $loginStatus->getToken();				
				} else {
					return false;
				}
			}
			return false;
		}catch( Exception $e ) {
			throw new Ext_Exception( $e );
		}
	}
	
	/**
 	 *
 	 * (cacheable) Apartir de un token devuelve el estado del usuario.
 	 * 
 	 * @param string Token
 	 * @return mixed false|Info
	 */
	public function getStatusByToken( $token )
	{
		try{
			$loginStatus = new SsoWS_Model_UserLoginStatus ();
			if( $loginStatus->getStatus( $token ) == 'T' ){
				return (array) $this->getInfo( 
					$loginStatus->getUsernameByToken( $token ) 
				);
			}
			return false;
		}catch( Exception $e ) {
			throw new Ext_Exception( $e );
		}		
	}

	/**
	 * 
	 * Cambia el estado de un usuario a offline
	 * @param string username
	 * @return boolean Status
	 */
	public function logout( $username )
	{
		try{
			$user = new Ext_Model_User();
			$userId = $user->getUserId( $username );
			if( empty( $userId ) ) {
				return false;
			}
			$loginStatus = new SsoWS_Model_UserLoginStatus();
			return $loginStatus->logout( $userId );
		}catch( Exception $e ) {
			throw new Ext_Exception( $e );
		}		
	}
	
	/**
	 * 
	 * Apartir de un username y una password, da de alta un usuario al sistema  
	 * @param string username
	 * @param string passowrd
	 * @param mixed Properties
	 * @return boolean true|false 
	 */
	public function register( $username, $password, $properties = array() )
	{
		try{
	        $userDb = new Ext_Model_User();
	        $row = $userDb->createRow();
			$row->owner_id = Zend_Registry::get('config')->user->login->ownerId;
	        
			$form = new Ext_Forms_EditUser();
			if( $form->isValid( array(
				'username' => $username,
				'password' => $password
			) )){
	        
				$user = $userDb->getUserByName( $form->getValue('username') );
		        if ( count( $user ) ) {
					throw new Ext_Exception(
						'El usuario ya existe en el sistema.'
					);
				}
				$extraData = array( 
		        	"username" => $form->getValue('username'),
		            "locked" => 'F' 
				);
		        $row->setFromArray( $extraData );
		        $row->changePassword($form->getValue('password') );

		        $userId = $row->save();
		        foreach	( $properties as $key=>$value){
		        	$this->addProperty( $userId, $key, $value );
		        }
		        return true;
			} else {
				throw new Ext_Exception('Los datos son invalidos.');
			}
		} catch( Exception $e ) {
			throw new Ext_Exception( $e );
		}		
	}	

	/**
	 * Actualiza los datos de un usuario
	 * 
	 * @param integer userId
	 * @param string credential
	 * @param mixed properties
	 * @return boolean true|false true si todo anubo bien o false.
	 */
	public function updateUserProperties( $userId, $credential, $properties = array() )
	{
		if ( $this->checkCredential( $userId, $credential ) === false ) {
			throw new Ext_Exception( 'El usuario y al credencial no son validos.' );
		}

		try{
			// actualizamos las properties
			foreach( $properties as $propertyName => $propertyValue ) {
				$this->updateProperty( $userId, $credential, $propertyName, $propertyValue );
			}

		} catch( Exception $e ) {
			throw new Ext_Exception( $e );
		}		
		return true;
	}
	
	/**
	 *
	 * Agrega o edita propiedades de un usuario
	 * 
	 * @param integer userId
	 * @param string key
	 * @param string value. 
	 * @return boolean true|false
	 */
	public function addProperty( $userId, $key, $value )
	{
		try{
			if( empty( $userId ) ) {
				return false;
			}

			$model = new SsoWS_Model_UserProperty();
			$data = new stdClass();
			$data->user_id = $userId;
			$data->property = $key;
			$data->value = $value;
			if( $model->save( $data ) ){
				return true;
			} 
			return false;
		}catch( Exception $e ) {
			throw new Ext_Exception( $e );
		}		
		
	}

	/**
	 *
	 * Actualizar las propiedades del usuario.
	 * 
	 * @param integer userId
	 * @param string credential
	 * @param string key
	 * @param string value. 
	 * @return boolean true|false
	 */
	public function updateProperty( $userId, $credential, $key, $value )
	{
		if ( $this->checkCredential( $userId, $credential ) === false ) {
			throw new Ext_Exception( 'El usuario y al credencial no son validos.' );
		}

		try{
			if( empty( $userId ) ) {
				return false;
			}

			$model = new SsoWS_Model_UserProperty();
			$query = $model->select()
				->where( 'user_id = ?', $userId )
				->where( 'property = ?', $key );
			$rows = $model->fetchAll($query);
			if ( count( $rows ) == 0 ) {
				$row = $model->createRow();
				$row->user_id = $userId;
				$row->property = $key;
			} else {
				$row = $rows->current();
			}

			$row->value = $value;
			$row->save();
		} catch( Exception $e ) {
			throw new Ext_Exception( $e );
		}		
		return true;
	}


	/**
	 *
	 * Borra todas la propieadades de un usuario.
	 * 
	 * @param integer userId
	 * @param string credential
	 * @return boolean true on success.
	 */
	public function clearProperties( $userId, $credential )
	{
		if ( $this->checkCredential( $userId, $credential ) === false ) {
			throw new Ext_Exception( 'El usuario y al credencial no son validos.' );
		}

		try{
			if( empty( $userId ) ) {
				return false;
			}

			$model = new SsoWS_Model_UserProperty();
			$where = $model->getAdapter()->quoteInto('user_id = ?', $userId);
			$model->delete($where);
		} catch( Exception $e ) {
			throw new Ext_Exception( $e );
		}		

		return true;
	}

	
	/**
	 * Cambia la password al usuario
	 * 
	 * @param integer userId
	 * @param string credential
	 * @param string new password
	 * @return boolean true on success.
	 */
	public function changePassword( $userId, $credential, $newPassword )
	{
		if ( $this->checkCredential( $userId, $credential ) === false ) {
			throw new Ext_Exception( 'El usuario y al credencial no son validos.' );
		}

		try{
	        $userDb = new Ext_Model_User();
			$user = $userDb->getUser( $userId );
			if ( count( $user ) == 0 ) {
				throw new Ext_Exception( 'El usuario no existe' );
			}
			$user->changePassword( $newPassword );
			$user->save();

		} catch( Exception $e ) {
			throw new Ext_Exception( $e );
		}		

		return true;

	}


	/**
	 *
	 * Activa la cuenta de un usuario
	 * @param string Username
	 * @return boolean true|false
	 */
	public function activate( $username )
	{
		return true;
	}
	
	/**
	 * 
	 * (cacheable) Contrala que los datos sean validos
	 * @param string Username
	 * @param string password
	 * @return boolean true|false
	 */
	public function validate( $username, $password = null )
	{
		try{
			$user = new Ext_Model_User();
			if( count( $user->getAuthenticatedUser( $username, $password, 1 )) ){
				return true;
			} else {
				return false;
			}
		}catch( Exception $e ) {
			throw new Ext_Exception( $e );
		}		
	}
	
	/**
	 * (cacheable) Devuelve la info de un usuario
	 * 
	 * @param string Username
	 * @return mixed false|Info
	 */
	public function getInfo( $username )
	{
		try{
			$user = new Ext_Model_User();
			$userId = $user->getUserId( $username );
			if( empty( $userId )){
				return false;
			}
			return $user->getUserComplete( $userId );
		}catch( Exception $e ) {
			throw new Ext_Exception( $e );
		}		
	}

	/**
	 * (cacheable) Devuelve el id del usuario a partir de un token
	 * 
	 * @param string Token
	 * @return mixed UserId|false
	 */
	public function getUserIdByUsername( $username )
	{
		try{
			$user = new Ext_Model_User();
			return $user->getUserId( $username );
		}catch( Exception $e ) {
			throw new Ext_Exception( $e );
		}		
	}
	
	/**
	 * (cacheable) Devuelve la info de un usuario a partir de un token
	 * 
	 * @param string Token
	 * @return array Info
	 */
	public function getInfoByToken( $token )
	{
		try{
			$userLoginStatus = new SsoWS_Model_UserLoginStatus();
			$username = $userLoginStatus->getUsernameByToken( $token );
			return $this->getInfo( $username );
		}catch( Exception $e ) {
			throw new Ext_Exception( $e );
		}		
	}

	/**
	 * (cacheable) Devuelve una lista de los roles, y recursos que tiene acceso 
	 * 
	 * @param string Username
	 * @param integer AppId
	 * @return array ACLDATA
	 */
	public function getAcl( $username, $appId )
	{
		try{
			$userInfo = array();
			$user = new Ext_Model_User();
			$userInfo['base'] = $user->getUserByName( $username )->toArray();
			unset( $userInfo['base']['password'] );
			$resource = new Ext_Model_Resource();
			$userInfo['resource'] = $resource->getResourceList( $appId );
			$userInfo['roles'] = $resource->getRoleByResource( $userInfo['base']['user_id'], $appId );
			$userInfo['acls'] = $resource->getAclByResource( $userInfo['base']['user_id'], $appId );
			return $userInfo;
		}catch( Exception $e ) {
			throw new Ext_Exception( $e );
		}		
		
	}
	
	public function addAcl( $username, $options )
	{
	}
		
	/**
	 *
	 * Desactiva la cuenta de un usuario
	 * @param String username
	 * @return mixed true|false
	 */
	public function desactivate( $username )
	{
		return true;
	}
	
}
